﻿using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using DotnetApp.Dtos;
using DotnetApp.Extensions;
using DotnetApp.Security;
using DotnetApp.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace DotnetApp.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class DemoController : ControllerBase
    {
        private readonly ILogger<DemoController> _logger;
        private readonly DataGatewayOptions _options;
        private readonly IHashHelper _hashHelper;
        private readonly ITextProtector _textProtector;
        private readonly JsonSerializerOptions _jsonOptions;

        public DemoController(ILogger<DemoController> logger, IOptions<DataGatewayOptions> options, IHashHelper hashHelper, ITextProtector textProtector, JsonSerializerOptions jsonOptions)
        {
            _logger = logger;
            _hashHelper = hashHelper;
            _textProtector = textProtector;
            this._jsonOptions = jsonOptions;
            _options = options.Value;
        }

        /// <summary>
        /// 接收来自数据网关推送的消息
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Post()
        {
            if (!Request.Headers.TryGetValue("x-signature", out var signature))
            {
                // logging and return error
                throw new Exception("Signature missed");
            }
            using var reader = new StreamReader(Request.Body, Encoding.UTF8);
            var body = await reader.ReadToEndAsync();
            if (!_hashHelper.ValidateSha1(body + _options.HashKey, signature))
            {
                // logging and return error
                throw new Exception("Signature validation failed");
            }

            if (_options.Encrypt)
            {
                body = _textProtector.Decrypt(body, _options.AesKey);
            }

            _logger.LogInformation(body);

            var input = JsonSerializer.Deserialize<MessageInput>(body, _jsonOptions);

            if (DateTimeOffset.Now.ToUnixTimeMilliseconds() - input.Timestamp > 10_000)
            {
                // 可选，时间戳过期
            }

            // Process messages
            ApiResult result;
            switch (input.Event)
            {
                case "webapp-a-test":
                    {
                        // 反序列化得到强类型。或者通过JsonDocument的API直接读取input.Body
                        var testInput = input.Body.ToObject<WebAppTestInput>();

                        // TODO 处理事件
                        // ...

                        // 返回结果
                        result = new ApiResult(0, "", DateTimeOffset.Now.ToUnixTimeMilliseconds(), null);
                    }
                    break;
                case "event-result":
                    {
                        // Got the result of message, Id = input.EventId
                        result = new ApiResult(0, "result received", DateTimeOffset.Now.ToUnixTimeMilliseconds(), null);
                    }
                    break;
                default:
                    result = new ApiResult(0, "ignored", DateTimeOffset.Now.ToUnixTimeMilliseconds(), null);
                    break;
            }

            // Return result
            var resultJson = JsonSerializer.Serialize(result, _jsonOptions);
            if (_options.Encrypt)
            {
                resultJson = _textProtector.Encrypt(resultJson, _options.AesKey);
            }
            var resultSignature = _hashHelper.Sha1(resultJson + _options.HashKey);
            var content = Content(resultJson, "application/sha1+json");
            Response.Headers.Add("x-signature", resultSignature);
            return content;
        }

        [HttpGet("send")]
        public async Task<IActionResult> Send([FromServices] DataGatewayHttpClient client)
        {
            var message = new
            {
                @event = "webapp-a-test",
                eventId = "123",
                body = new { title = "这是个异步消息，处理结果发送到合作方提供的回调接口上" },
                timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds()
            };
            var result = await client.SendAsync(message);
            return Content(result);
        }
    }
}
